package route

import (
	"crypto/rand"
	"github.com/dgrijalva/jwt-go"
	"github.com/gomodule/redigo/redis"
	protobuf "route/protobuf"
	"strings"
	"time"
)

// 返回 jwt signature
func splitSignatureFromHeader(authorization string) (signature string, mapClaims jwt.MapClaims, err error) {
	lIndex := strings.LastIndex(authorization, ".")
	if lIndex < 0 {
		return "", nil, ErrIrregularSign
	}
	token2, err := jwt.Parse(authorization, func(tk *jwt.Token) (interface{}, error) {
		if _, ok := tk.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, ErrUnableParse
		}
		return "", nil
	})

	if claims, ok := token2.Claims.(jwt.MapClaims); ok {
		return authorization[lIndex+1:], claims, nil
	} else {
		return "", nil, ErrUnableParse
	}
}

// 创建 jwt token
func newToken(user string, expire int64) (signature string, tokenS string, err error) {
	b := make([]byte, 128)
	if _, err := rand.Read(b); err != nil {
		return "", "", err
	}

	now := time.Now()
	mapClaims := jwt.MapClaims{
		"sub": user,
		"exp": now.Add(dynamic.frontendExpire).Unix(), // 过期时间从 dynamicName.frontendExpire 规定
		"nbf": now.Unix(),                             // 在 now.Unix() 之前不可用
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, mapClaims)
	if tokenS, err = token.SignedString(b); err != nil {
		return "", "", err
	}
	signature = tokenS[strings.LastIndex(tokenS, ".")+1:]
	return
}

// 验证 token 状态 : 是否存在, 是否过期
// NOTE: id 是用来弥补 recordOperation 的 idR, 如果删除?
func checkToken(conn redis.Conn, redistb string, authToken string) (isExistORNotExpire byte, s0 []byte, err error) {
	// 从 redis 验证 token 并且拿 具体的信息
	// s, err := redis.ByteSlices(conn.Do("HMGET", redistb+authToken, "id", "user", "expire"))
	s0, err = redis.Bytes(conn.Do("GET", redistb+authToken))
	if err != nil {
		return notExist, nil, err
	}
	s := &protobuf.Token{}
	err = s.XXX_Unmarshal(s0)
	if err != nil {
		// redis 的 token 无效
		return existButFailParse, s0, err
	}
	t, err := time.Parse(TimeFormat, s.Expire)
	if err != nil {
		// redis 的 token 无效
		return existButFailParse, s0, err
	}
	// token 存在
	if time.Now().Unix() > t.Unix() {
		// 过期
		return existButExpire, s0, nil
	}
	return existAndNotExpire, s0, nil
}

// 新建一个 token 用于避免重复提交[POST, PUT]
// func newUUIDToken(header string) (string, error) {
// 	uuid, err := gouuid.NewV4()
// 	if err != nil {
// 		return "", err
// 	}
// }
